package cn.tedu.charging.order.mqtt;

import cn.tedu.charging.common.pojo.JsonResult;
import cn.tedu.charging.common.pojo.param.ChargingProcessParam;
import cn.tedu.charging.common.pojo.vo.ChargingProcessVO;
import cn.tedu.charging.common.utils.JsonUtils;
import cn.tedu.charging.order.common.ChargingConstants;
import cn.tedu.charging.order.common.MqttConstants;
import cn.tedu.charging.order.common.OrderStatusConstants;
import cn.tedu.charging.order.pojo.dto.ChargingProcessDTO;
import cn.tedu.charging.order.pojo.dto.ChargingResultDTO;
import cn.tedu.charging.order.pojo.po.ChargingOrderFailPO;
import cn.tedu.charging.order.pojo.po.ChargingOrderSuccessPO;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.*;

@Slf4j
public class MqttConsumer implements MqttCallbackExtended {


    private MqttClient mqttClient;  
    private MqttContext mqttContext;

    public MqttConsumer() {
    }

    public MqttConsumer(MqttClient mqttClient, MqttContext mqttContext) {
        this.mqttClient = mqttClient;
        this.mqttContext = mqttContext;
    }

    public void setMqttClient(MqttClient mqttClient,MqttContext mqttContext) {
        this.mqttClient = mqttClient;
        this.mqttContext = mqttContext;
    }

    @Override
    public void connectComplete(boolean b, String s) {
        log.debug("connectComplete 连接成功: b:{},s:{}", b,s);
        String topicChargingResult = MqttConstants.TOPIC_CHARGING_RESULT;
        String topicChargingProcess = MqttConstants.TOPIC_CHARGING_PROCESS;
        try {
            log.debug("订单服务订阅设备返回的 <<开始充电结果>> Topic:{}", topicChargingResult);
            mqttClient.subscribe(topicChargingResult);
            log.debug("订单服务订阅设备返回的 <<开始充电结果>> Topic:{},成功", topicChargingResult);

            log.debug("订单服务订阅设备返回的 <<同步充电进度>> Topic:{}", topicChargingProcess);
            mqttClient.subscribe(topicChargingProcess);
            log.debug("订单服务订阅设备返回的 <<同步充电进度>> Topic:{},成功", topicChargingProcess);
        } catch (MqttException e) {
            //打印异常信息 可能进行重试，接入告警系统 告警
            throw new RuntimeException(e);
        }
    }

    @Override
    public void connectionLost(Throwable throwable) {
        log.debug("connectionLost 连接丢失: {}", throwable);
        // 重连
        // mqttClient.connect();
    }

    @Override
    public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
        log.debug("messageArrived 收到设备发送的消息:topic:{},message:{}", topic, mqttMessage);
        handleChargingProcess(mqttMessage);
        if (MqttConstants.TOPIC_CHARGING_PROCESS.equals(topic)){
            log.debug("处理设备同步的开始充电进度");
        } else if (MqttConstants.TOPIC_CHARGING_RESULT.equals(topic)){
            log.debug("处理设备同步的开始充电结果");
            handleChargingResult(mqttMessage);
        }

    }

    /**
     * 处理设备同步的开始充电进度
     * @param mqttMessage
     */

    private void handleChargingProcess(MqttMessage mqttMessage) {
        ChargingProcessDTO chargingProcessDTO = null;
        try {
            chargingProcessDTO = JsonUtils.fromJson(mqttMessage.toString(), ChargingProcessDTO.class);
        } catch (Exception e) {
            // 如果多次失败，应该告警
            log.error("订单服务解析设备返回的开始充电结果失败", e);
        }
        log.debug("收到设备同步充电进度数据:{}",chargingProcessDTO);

       if (chargingProcessDTO != null){
           ChargingProcessParam chargingProcessParam = new ChargingProcessParam();
           chargingProcessParam.setOrderNo(chargingProcessDTO.getOrderNo());
           chargingProcessParam.setGunId(chargingProcessDTO.getGunId());
           log.debug("开始调用计价服务计算价格入参:{}", chargingProcessParam);
           ChargingProcessVO cost = getChargingProcessVO(chargingProcessParam);
           log.debug("开始调用计价服务计算价格入参:{},出参:{}", chargingProcessParam, cost);
       }
    }


    private ChargingProcessVO getChargingProcessVO(ChargingProcessParam chargingProcessParam) {
        JsonResult<ChargingProcessVO> result = mqttContext.getCostClient().calculateCost(chargingProcessParam);
        if (result != null) {
            return result.getData();
        }
        return null;
    }



    private void handleChargingResult(MqttMessage mqttMessage) {
        ChargingResultDTO chargingResultDTO = null;
        try {
            chargingResultDTO = JsonUtils.fromJson(mqttMessage.toString(), ChargingResultDTO.class);
        } catch (Exception e) {
            // 如果多次失败，应该告警
            log.error("订单服务解析设备返回的开始充电结果失败", e);
        }
        log.debug("收到设备返回的充电结果:{}",chargingResultDTO);


        if (chargingResultDTO != null){
            if (ChargingConstants.CHARGING_RESULT_SUCCESS.equals(chargingResultDTO.getResult())) {
                handleSuccessMessage(chargingResultDTO);
            }else {
                handleFailMessage(chargingResultDTO);
            }
        }

    }

    /**
     * 处理开始充电失败消息
     * @param chargingResultDTO
     */
    private void handleFailMessage(ChargingResultDTO chargingResultDTO) {
        log.debug("设备发送的消息是 开始充电失败 的消息");
        ChargingOrderFailPO chargingOrderFailPO = new ChargingOrderFailPO();
        chargingOrderFailPO.setBillId(chargingResultDTO.getOrderNo());
        chargingOrderFailPO.setFailDesc("设备有响应,开始充电失败");
        log.debug("保存订单失败记录,{}", chargingOrderFailPO);
        int row = mqttContext.getOrderFailMapper().insert(chargingOrderFailPO);
        log.debug("保存订单失败记录:{},影响行数:{}", chargingOrderFailPO, row);
        //todo
        log.debug("设备发送的消息是 开始充电失败 <<通知用户>>,提醒用户更换设备");
        log.debug("给用户发送优惠券，表示歉意，给用户心灵上的安慰");
        log.debug("修改枪的状态为 <<故障>>");
        log.debug("<<通知设备管理员>> 进行设备的检修");
    }


    /**
     * 处理开始充电成功消息
     * @param chargingResultDTO
     */
    private void handleSuccessMessage(ChargingResultDTO chargingResultDTO) {
        log.debug("设备发送的消息是 开始充电成功 的消息");
        ChargingOrderSuccessPO chargingOrderSuccessPO = new ChargingOrderSuccessPO();
        chargingOrderSuccessPO.setBillId(chargingResultDTO.getOrderNo());
        chargingOrderSuccessPO.setGunId(chargingResultDTO.getGunId());
        chargingOrderSuccessPO.setBillStatus(OrderStatusConstants.ORDER_STATUS_CHARGING);
        log.debug("保存订单成功记录,{}", chargingOrderSuccessPO);
        int row = mqttContext.getOrderSuccessMapper().insert(chargingOrderSuccessPO);
        log.debug("保存订单成功记录:{},影响行数:{}", chargingOrderSuccessPO, row);
        //todo 设备会定时的和订单服务同步充电进度数据 直到车辆电池充满
    }

    @Override
    public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
        log.debug("deliveryComplete 消息发送完成: {}", iMqttDeliveryToken);
    }
}
